package com.jin.webvideo.base.dc;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.concurrent.*;

/**
 * 异步执行器
 *
 * @author biao532
 * @date 2023/12/03 10:53
 **/
public class AsynExecutor {
    public static final int STATS_SUCCESS = 0;
    public static final int STATS_FAIL = 1;
    public static final int STATS_TIMEOUT = 2;
    public static final int STATS_OTHER = 3;
    private volatile static AsynExecutor singleton;
    public static AsynExecutor singleton() {
        if (singleton == null) {
            synchronized (AsynExecutor.class) {
                if (singleton == null) {
                    singleton = new AsynExecutor();
                }
            }
        }
        return singleton;
    }

    private ExecutorService executorService;
    private int second;
    private AsynExecutor() {
        this.executorService = Executors.newSingleThreadExecutor();
        this.second = 3;
    }
    public int submit(DSExecutor executor) {
        ERunnable c = new ERunnable(executor);
        Future<Boolean> f = executorService.submit(c);
        try{
            // 是否正常结束
            boolean over = f.get(3, TimeUnit.SECONDS);
            return over?STATS_SUCCESS:STATS_FAIL;
        }
        catch (TimeoutException | ExecutionException e){
            e.printStackTrace();
            // 正在运行
            if (!f.isDone()) {
                // 停止运行
                f.cancel(true);
                // 强制停止线程
                c.destroy();
            }
            return STATS_TIMEOUT;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return STATS_OTHER;
    }

    private class ERunnable implements Callable<Boolean> {
        private static final VarHandle RUNNER;
        static {
            MethodHandles.Lookup l = MethodHandles.lookup();
            try {
                RUNNER = l.findVarHandle(ERunnable.class, "runner", Thread.class);
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new ExceptionInInitializerError(e);
            }
        }
        private DSExecutor executor;
        private volatile Thread runner;
        public ERunnable(DSExecutor executor) {
            this.executor = executor;
        }
        @Override
        public Boolean call() {
            try {
                if (RUNNER.compareAndSet(this, null, Thread.currentThread())) {
                    executor.exec();
                }
                return true;
            } catch (ScriptException e) {
                e.printStackTrace();
            }
            catch (Throwable e) {
                // 捕获可能的异常
                e.printStackTrace();
            }
            return false;
        }

        public void destroy() {
            if (RUNNER.compareAndSet(this, null, Thread.currentThread())) {
                return;
            }
            executor = null;
            if (runner.isAlive()) {
                runner.stop();
            }
        }
    }
}
